package utils.cli;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class CommandLine {
    private final ArrayList<String> mainArgs = new ArrayList<>();
    private final Map<String, String> commandLineMap = new HashMap<>();
    private final Options options;

    public CommandLine(Options options, String[] args) {
        this.options = options;

        int i = 0;
        for (; i < args.length; i++) {
            String arg = args[i];

            if (arg.charAt(0) == '-') {
                break;
            }

            this.mainArgs.add(arg);
        }

        for (; i < args.length; i++) {
            String arg = args[i];

            if (arg.charAt(0) == '-' && arg.charAt(1) == '-') {
                String longOption, value;
                int split = arg.indexOf('=');

                if (split == -1) {
                    longOption = arg.substring(2);
                    value = "";
                } else {
                    longOption = arg.substring(2, split);
                    value = arg.substring(split + 1);
                }

                if (options.longShortMap.containsKey(longOption)) {
                    this.commandLineMap.put(options.longShortMap.get(longOption), value);
                }
            }
            else if (arg.charAt(0) == '-') {
                String shortOption;
                shortOption = arg.substring(1);

                if (options.optionsMap.containsKey(shortOption)) {
                    if (options.optionsMap.get(shortOption).hasVal && i + 1 < args.length && args[i + 1].charAt(0) != '-') {
                        this.commandLineMap.put(shortOption, args[i + 1]);
                        i++;
                    } else {
                        this.commandLineMap.put(shortOption, "");
                    }
                }
            }
            else {
                mainArgs.add(arg);
            }
        }

    }

    public boolean has(int mainArgsIndex) {
        return mainArgs.size() > mainArgsIndex;
    }
    public boolean has(String option) {
        return commandLineMap.containsKey(option);
    }
    public boolean hasOptionValue(String option) {
        return has(option) && !commandLineMap.get(option).equals("");
    }
    public String get(int mainArgsIndex) {
        if (has(mainArgsIndex)) return mainArgs.get(mainArgsIndex);
        return null;
    }
    public String get(String option) {
        return commandLineMap.get(option);
    }
    public int getMainArgsNum() {
        return mainArgs.size();
    }
    public boolean get2Boolean(int mainArgsIndex, boolean defaultValue) {
        if (!has(mainArgsIndex)) {
            return defaultValue;
        }
        return Boolean.parseBoolean(get(mainArgsIndex));
    }
    public boolean get2Boolean(String option, boolean nullDefaultValue, boolean emptyDefaultValue) {
        if (!has(option)) {
            return nullDefaultValue;
        }
        if (!hasOptionValue(option)) {
            return emptyDefaultValue;
        }
        return Boolean.parseBoolean(get(option));
    }

    public void printAll() {
        System.out.println("cmd:");
        System.out.print("\tmain-args: ");
        for (String arg: mainArgs) {
            System.out.print(arg);
            System.out.print(' ');
        }
        System.out.println();

        System.out.println("\toptions:");
        for (Map.Entry<String, String> entry : commandLineMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.printf(
                    "\t-%-5s--%-15s%-9b%s%n",
                    key,
                    options.optionsMap.get(key).longOption,
                    options.optionsMap.get(key).hasVal,
                    value.equals("") ? "<non-val>" : value);
        }
    }
}
